package me.landery.modules.sinco.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import lombok.RequiredArgsConstructor;
import me.landery.exception.BadRequestException;
import me.landery.modules.sinco.domain.Application;
import me.landery.modules.sinco.repository.ApplicationRepository;
import me.landery.modules.sinco.service.ApplicationService;
import me.landery.modules.sinco.service.dto.ApplicationDto;
import me.landery.modules.sinco.service.dto.ApplicationQueryCriteria;
import me.landery.modules.sinco.service.mapstruct.ApplicationMapper;
import me.landery.modules.sinco.util.AppUtils;
import me.landery.modules.system.service.UserService;
import me.landery.modules.system.service.dto.UserDto;
import me.landery.modules.system.service.mapstruct.UserMapper;
import me.landery.utils.*;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "sinco_application")
public class ApplicationServiceImpl implements ApplicationService {
    private final ApplicationRepository applicationRepository;
    private final ApplicationMapper applicationMapper;
    private final UserService userService;
    private final UserMapper userMapper;
    @Override
    public Map<String,Object> queryAll(ApplicationQueryCriteria criteria, Pageable pageable){
//        //获取当前登录的用户名
//        if (criteria.getUsername() != null && !criteria.getUsername().equals(SecurityUtils.getCurrentUsername())) {
//            throw new BadRequestException("查询失败，只能查询自己的应用");
//        }
        Page<Application> page = applicationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(applicationMapper::toDto));
    }

    @Override
    public List<ApplicationDto> queryAll(ApplicationQueryCriteria criteria){

        return applicationMapper.toDto(applicationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }


    @Override
    @Transactional
    public ApplicationDto findById(Long id) {
        Application application = applicationRepository.findById(id).orElseGet(Application::new);
        ValidationUtil.isNull(application.getId(),"App","id",id);
        return applicationMapper.toDto(application);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApplicationDto create(Application resources) {
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.setId(snowflake.nextId());
        return applicationMapper.toDto(applicationRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApplicationDto create(ApplicationDto resources) {
        //根据拿到的应用名称、备注、应用状态创建应用
        //判断应用名称是否重复
        UserDto userDto = userService.findById(SecurityUtils.getCurrentUserId());

        if (resources.getStatus() != 0 && resources.getStatus() != 1){
            throw new BadRequestException("应用状态非法！");
        }
        Application app = applicationRepository.findByUserIdAndName(SecurityUtils.getCurrentUserId(),resources.getName());
        if (app != null){
            throw new BadRequestException("应用名称已存在！");
        }
        Application application = new Application();
        application.setName(resources.getName());
        application.setRemark(resources.getRemark());
        application.setStatus(resources.getStatus());
        //生成 appid和secretkey
        String appid = AppUtils.getAppId();
        String secretkey = AppUtils.getAppSecret(appid);
        //判断 appid是否使用过
        Application app1 = applicationRepository.findByAppid(appid);
        if (app1 != null){
            throw new BadRequestException("appid生成失败，appid已存在！请重试");
        }
        application.setAppid(appid);
        application.setSecretkey(secretkey);
        application.setUser(userMapper.toEntity(userDto));

        return applicationMapper.toDto(applicationRepository.save(application));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Application resources) {
        Application application = applicationRepository.findById(resources.getId()).orElseGet(Application::new);
        ValidationUtil.isNull( application.getId(),"App","id",resources.getId());
        application.copy(resources);
        applicationRepository.save(application);
    }

    @Override
    public void update(ApplicationDto resources) {
        Application application = applicationRepository.findById(resources.getId()).orElseGet(Application::new);
        ValidationUtil.isNull( application.getId(),"App","id",resources.getId());

        //判断应用名称是否重复
        Application app = applicationRepository.findByUserIdAndName(SecurityUtils.getCurrentUserId(),resources.getName());
        if (app != null && !app.getId().equals(resources.getId())){
            throw new BadRequestException("应用名称已存在！");
        }
        application.setName(resources.getName());
        application.setRemark(resources.getRemark());
        application.setStatus(resources.getStatus());
        applicationRepository.save(application);
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            applicationRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<ApplicationDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ApplicationDto app : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("用户id", app.getUser().getId());
            map.put("应用id", app.getAppid());
            map.put("接口访问密钥", app.getSecretkey());
            map.put("应用备注", app.getRemark());
            map.put("应用状态0禁用，1启用", app.getStatus());
            map.put("创建日期", app.getCreateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Application getByAppId(String appId) {
        return applicationRepository.findByAppid(appId);
    }
}
